package com.zlyx.easy.web.web.controller;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zlyx.easy.core.exception.BusinessException;
import com.zlyx.easy.core.utils.JsonUtils;
import com.zlyx.easy.core.utils.RandomUtils;
import com.zlyx.easy.core.utils.StringUtils;
import com.zlyx.easy.swagger.annotations.SpringMapping;
import com.zlyx.easy.web.web.mybatis.AbstractMapper;
import com.zlyx.easy.web.web.service.AbstractService;

/**
 * @Auth 赵光
 * @Describle
 * @Date 2019年1月4日 下午8:59:49
 */
public class AbstractController<Service extends AbstractService<? extends AbstractMapper<T>, T>, T> {

	protected Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	protected Service baseService;

	/**
	 * 分页查询
	 * 
	 * @param pageNum
	 * @param pageSize
	 * @param entity
	 * @return
	 */
	@SpringMapping(notes = "分页查询", todo = { "分页查询" }, value = { "/page" }, method = RequestMethod.GET)
	public Page<T> page(@RequestParam(name = "pageNum", defaultValue = "0") Long current,
			@RequestParam(name = "pageSize", defaultValue = "10") Long size, T entity) {
		return doPage(current, size, entity);
	}

	/**
	 * 分页操作
	 * 
	 * @param current 当前页数
	 * @param size    页面大小
	 * @param entity  参数
	 * @return
	 */
	public Page<T> doPage(long current, long size, T entity) {
		return this.baseService.page(new Page<>(current, size), new QueryWrapper<T>(entity));
	}

	/**
	 * 条件查询
	 * 
	 * @param entity
	 * @return
	 */
	@SpringMapping(notes = "条件查询", todo = { "条件查询" }, value = { "/list" }, method = RequestMethod.GET)
	public List<Map<String, Object>> list(T entity) {
		return this.baseService.listMaps(new QueryWrapper<T>(entity));
	}

	/**
	 * 根据id查询
	 * 
	 * @param id
	 * @return
	 */
	@SpringMapping(notes = "根据id查询", todo = { "根据id查询" }, value = { "/get/{id}" }, method = RequestMethod.GET)
	public T getById(@PathVariable(name = "id") Serializable id) {
		return this.baseService.getById(id);
	}

	/**
	 * 新增记录
	 * 
	 * @param entity
	 * @return
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	@SpringMapping(notes = "新增", todo = { "新增" }, value = { "/save" }, method = RequestMethod.POST)
	public boolean save(@Validated T entity) throws Exception {
		if (Boolean.FALSE == doBeforeSave(entity)) {
			BusinessException.throwAndLogException("参数对象验证失败");
		}
		return this.baseService.save(entity);
	}

	/**
	 * 批量新增
	 * 
	 * @param entityList
	 * @return
	 * @throws Exception
	 */
	@SpringMapping(notes = "批量新增", todo = { "批量新增" }, value = { "/save-batch" }, method = RequestMethod.POST)
	public boolean saveBatch(@RequestBody List<T> entityList) throws Exception {
		if (entityList == null || entityList.isEmpty()) {
			BusinessException.throwAndLogException("参数对象列表为空");
		}
		for (T entity : entityList) {
			// 如果返回失败，那么结束操作
			if (Boolean.FALSE == doBeforeSave(entity)) {
				BusinessException.throwAndLogException("参数验证失败");
			}
		}
		return this.baseService.saveOrUpdateBatch(entityList);
	}

	/**
	 * 保存对象前自定义定制化操作
	 * 
	 * @param entity
	 * @throws Exception
	 */
	public boolean doBeforeSave(T entity) throws Exception {
		if (entity == null) {
			return false;
		}
		Field field = entity.getClass().getDeclaredField("id");
		field.setAccessible(true);
		if (field != null) {
			Object value = field.get(entity);
			if (value == null || "".equals(value)) {
				Class<?> fieldType = field.getType();
				if (String.class == fieldType) {
					field.set(entity, RandomUtils.randomUUID());
				} else {
					field.set(entity, RandomUtils.randomNum());
				}
			}
		}
		return true;
	}

	/**
	 * 根据id批量更新
	 * 
	 * @param entity
	 * @return
	 * @throws Exception
	 */
	@SpringMapping(notes = "根据id批量更新", todo = { "根据id批量更新" }, value = { "/update" }, method = RequestMethod.PUT)
	public boolean update(T entity) throws Exception {
		if (Boolean.FALSE == doBeforeSave(entity)) {
			BusinessException.throwAndLogException("参数对象验证失败");
		}
		return this.baseService.updateById(entity);
	}

	/**
	 * 批量更新
	 * 
	 * @param entityList
	 * @return
	 * @throws Exception
	 */
	@SpringMapping(notes = "批量更新", todo = { "批量更新" }, value = { "/update-batch" }, method = RequestMethod.PUT)
	public boolean updateBatchById(@RequestBody List<T> entityList) throws Exception {
		if (entityList == null || entityList.isEmpty()) {
			BusinessException.throwAndLogException("参数对象列表为空");
		}
		for (T entity : entityList) {
			// 如果返回失败，那么结束操作
			if (Boolean.FALSE == doBeforeSave(entity)) {
				BusinessException.throwAndLogException("参数验证失败");
			}
		}
		return this.baseService.updateBatchById(entityList);
	}

	/**
	 * 根据id删除
	 * 
	 * @param id
	 * @return
	 */
	@SpringMapping(notes = "根据id删除", todo = { "根据id删除" }, value = { "/delete/{id}" }, method = RequestMethod.DELETE)
	public boolean removeById(@PathVariable("id") Serializable id) {
		return this.baseService.removeById(id);
	}

	/**
	 * 批量删除(id数组)
	 * 
	 * @param idList
	 * @return
	 * @throws Exception
	 */
	@SpringMapping(notes = "批量删除", todo = { "批量删除" }, value = { "/delete-batch" }, method = RequestMethod.DELETE)
	public boolean deleteByIds(@RequestBody String ids) throws Exception {
		return this.baseService.removeByIds(JsonUtils.toList(ids));
	}

	/**
	 * 批量删除(逗号分隔的id字符串)
	 * 
	 * @param idList
	 * @return
	 */
	@SpringMapping(notes = "批量删除", todo = { "批量删除" }, value = { "/remove-batch" }, method = RequestMethod.DELETE)
	public boolean removeByIds(@RequestParam(name = "ids") String ids) {
		return StringUtils.isEmpty(ids) ? true : this.baseService.removeByIds(Arrays.asList(ids.split(",")));
	}

}
